package actionHandlers;

/************************************************************
*   This class is designed to acknowledge a mouse click down 
*   (on the canvas) and append shapes to the canvas.shapeList
*   on mouse click up.
************************************************************/

import java.awt.*; //need for the paint
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
// libraries for glazedlists
import ca.odell.glazedlists.*;

import cuShapes.*;
import java.util.List;

public class ShapeDraw implements MouseListener, MouseMotionListener {
	
	final static BasicStroke thinStroke = new BasicStroke(2.0f);
	final static BasicStroke wideStroke = new BasicStroke(8.0f);

	private PaintTimer time;
	private boolean editingShape = false;
	private PQShape currentShape = null;
	private EventList<PQShape> shapeList;
	private EventList<PQShape> arrowList;

	public ShapeDraw(){
		
		time = new PaintTimer(20);
		shapeList = new BasicEventList<PQShape>();
		arrowList = new BasicEventList<PQShape>();
		shapeList.addListEventListener(new ShapeArrowListListener());
		arrowList.addListEventListener(new ShapeArrowListListener());
	}

	public void clear(){
		shapeList.clear();
		arrowList.clear();
		currentShape = null;
	}
	public List<PQShape> getShapeList(){
		return shapeList;
	}
	public List<PQShape> getArrowList(){
		return arrowList;
	}
	
	public PQShape getCurrentShape() {
		return currentShape;
	}
	public void setCurrentShape(PQShape s) {
		currentShape = s;
		currentShape.setSelected(true);
		currentShape.setSelected(false);
		time.start();
		time.stop();
	}
	
	public void drawAll(Graphics g){
		Graphics2D g2 = (Graphics2D)g;
		g2.setStroke(thinStroke);
		g2.setColor(Color.black);

		if(currentShape != null){
			currentShape.drawToCanvas(g2);
			//sidebar.setShape(currentShape);
		}
		
		//draw all the rest
		for(PQShape a : arrowList){
			a.drawToCanvas(g2);
		}
		for(PQShape x : shapeList){
			x.drawToCanvas(g2);
		}


	}

	public void mousePressed(MouseEvent e) {
		//first look for collision with a shape
		for(PQShape x : shapeList){ 
			if(x.hitRect(e.getPoint())){ //workingRect will change to reflect hit.
				currentShape = x;
				currentShape.setSelected(true);
				
				currentShape.setWorkingRect(x.getWorkingRect());
				editingShape = true;
				time.start();			
			}
			//look for arrow connections
			else if(x.getRect().contains(e.getPoint())){
				CurrentShape.setSelectedShape("Arrow");
				Point p = x.getCenterRect().getLocation();
				currentShape = CurrentShape.getSelectedShape(p);
				((Connectable)x).add_arrowOut((Arrow)currentShape);
				editingShape = true;
				time.start();
			}
		
		}
		//Are we moving an arrow??
		for(PQShape a : arrowList){
			if(a.hitRect(e.getPoint())){
				currentShape = a;

				currentShape.setSelected(true);
				
				currentShape.setWorkingRect(a.getWorkingRect());
				editingShape = true;
				time.start();
			}
		}
		
		
		//this will draw a new shape to the screen
		if(!editingShape){
			/*
			 * If we are here, we need to ask the shape button what shape is selected,
			 *  then we 'new' it.  smart shape should do all this for us internally
			 *  when we call get shape.
			 *  after we get the shape, we give it a start and end.
			 */  
			currentShape = CurrentShape.getSelectedShape(e.getPoint());
			
			time.start();
		}
		
	}

	/*********************************************************
	 *   Here we are either setting the end for a new shape,
	 *      or moving an existing shape.  
	 *        Need a 'smart' currentShape. that can tell which
	 *        rect (tl,...,br) was selected, and how to resize.
	 *        
	 *        This method should just let the current shape that the final 
	 *          end location has been selected.
	 *          
	 */
	public void mouseReleased(MouseEvent e) {
		// make sure currentShape isn't already in ShapeList
		if(currentShape instanceof cuShapes.Arrow){
			if(!arrowList.contains(currentShape)){
				for(PQShape s : shapeList){
					if(s.getRect().contains((e.getPoint()))){
						arrowList.add((Arrow)currentShape);
						((Connectable)s).add_arrowIn((Arrow)currentShape);
						// commented out bc arrows are added everytime only added when they connect two shapes
						// was causing problems with the arrow having a null propertychangelistener
						currentShape.setSelected(true);
						currentShape.setSelected(false);
					}
				}			
			} else
				currentShape.setSelected(false);
		}
		else{
			if(!shapeList.contains(currentShape)) {
				shapeList.add((Connectable)currentShape);
				currentShape.setSelected(true);
				currentShape.setSelected(false);
			} else
				currentShape.setSelected(false);
		}	
		
		time.stop();
		editingShape = false;
	}
	
	public void mouseClicked(MouseEvent e) {}
	public void mouseEntered(MouseEvent e) {}
	public void mouseExited(MouseEvent e) {}
	
	public void mouseDragged(MouseEvent e) {
		currentShape.moveWorkingRect(e.getPoint());
	}

	public void mouseMoved(MouseEvent e) {}
	
}
